/*******************************************************************************
 * Copyright 2011 @ Kapil Viren Ahuja
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.kapil.framework.concurrent.impl;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

import com.kapil.framework.concurrent.IBroker;

/**
 * <p>
 * Implementation of {@link IBroker} that uses {@link ArrayBlockingQueue} as the data store.
 * </p>
 * 
 * @author Kapil Viren Ahuja
 *
 * @param <V>
 */
public class AsyncQueueBroker<V> extends AbstractBroker<V>
{
    ArrayBlockingQueue<V> queue;

    
    /**
     * Constructor with no parameters. It will initialize the {@link IBroker} with following settings:
     * 
     * <ul>
     * <li>Capacity: 100</li>
     * <li>Timeout: 3 seconds</li>
     * </ul>
     * 
     */
    public AsyncQueueBroker()
    {
        this(100);
    }


    /**
     * Constructor that accepts the capacity as the parameter. It will initialize the {@link IBroker} with following
     * settings:
     * 
     * <ul>
     * <li>Capacity: as provided</li>
     * <li>Timeout: 3 seconds</li>
     * </ul>
     * 
     */
    public AsyncQueueBroker(int capacity)
    {
        this(capacity, 3);
    }


    /**
     * Constructor with parameters for capacity and timeout (in seconds)
     * 
     * <ul>
     * <li>Capacity: 100</li>
     * <li>Timeout: 3 seconds</li>
     * </ul>
     * 
     */
    public AsyncQueueBroker(int capacity, int timeoutDuration)
    {
        super(capacity, timeoutDuration);
        queue = new ArrayBlockingQueue<V>(100);
    }


    /**
     * <p>
     * Provides implementation for {@link IBroker#put(Object)} by putting the object in the Queue using
     * the underlying {@link ArrayBlockingQueue} implementation. This method will add the data 
     * at the end of the queue.
     * </p>
     * 
     * <p>
     * In addition, if the underlying queue is full, this method will put the {@link Thread} in wait 
     * state until the {@link ArrayBlockingQueue} has memory to receive any further data,
     * </p>
     * 
     */
    @Override
    public void put(V data) throws InterruptedException
    {
        this.queue.put(data);
    }


    /**
     * <p>
     * Provides implementation for {@link IBroker#get()} by fetching the object in the Queue using
     * the underlying {@link ArrayBlockingQueue} implementation. This method will get the data 
     * from the top of the queue using the FIFO method.
     * </p>
     * 
     * <p>
     * In addition, if there are no objects in the underlying queue i.e. the queue is empty, this method 
     * will put the {@link Thread} in wait state until the {@link ArrayBlockingQueue} has objects.
     * </p>
     * 
     */
    @Override
    public V get() throws InterruptedException
    {
        return this.queue.poll(super.timeoutDuration, TimeUnit.SECONDS);
    }
}
